#ifndef PHYSIC
# define PHYSIC

# include <iostream>
# include <list>
# include <vector>
# include <set>
# include <map>

# include <math/vector.hh>
# include <math/plane.hh>
# include <request/request.hh>

# include <boost/shared_ptr.hpp>

# include <tbb/concurrent_queue.h>

# include "bounding.hh"
# include "bounding-sphere.hh"
# include "fps-zone.hh"
# include "../octree/octree_rts.hh"

# include "object.hh"
# include "../misc/obj-vect.hh"

class Physic
{
  typedef std::list<Object*>::const_iterator objIterator;

public:
  Physic (ObjVect& o);
  ~Physic ();
  // Update movement, forces, gravity, ...
  void update (double elaps);

  const std::set<Object*>& mov_obj () const;
  const std::set<Object*>& unmov_obj () const;

  void add_zone (FpsZone* z) { zone_.push_back (z); }

  // Bridle the physic engine.
  static const double TIMESTEP = 0.03;

  //friction
  static const double FRICTION = 0.005;

  // Gravity
  static const Vector3f GRAVITY;

private:
  // Check collisions + Where + move the objects.
  void do_collisions (std::set<Object*>::iterator i, std::list<Object*>* inter_list);

  // Reaction.
  void sphere_sphere_collision (std::set<Object*>::iterator i, Object* other);
  void sphere_cube_collision (std::set<Object*>::iterator i, Object* other);
  void cube_cube_collision (std::set<Object*>::iterator i, Object* other);
  void wall_collision (std::set<Object*>::iterator i);
  void plane_sphere_collision (std::set<Object*>::iterator i, Plane& p);

  // Walls
  std::list<Plane> walls_;

protected:
  void resolve_collisions ();
  ObjVect& obj_list_;
  std::set<Object*> mov_obj_;
  std::set<Object*> unmov_obj_;
  std::map<Object*, Vector3f> old_obj_pos_;
  std::map<Object*, Vector3f> final_obj_mov_;
  PhysicFunctor* pf_;
  OctreeRts* o_rts_;

  //zone
  std::list<FpsZone*> zone_;
};

#endif
